package twoD.IsoPfem;

import inf.jlinalg.Vector2D;

import java.util.ArrayList;

public abstract class Face implements IFace {

	protected ArrayList<Node> nodes_;
	protected ArrayList<IEdge> edges_;
	private int[][] dofNumbers_;
	private Constraint constraint_;
	private int nModes_;
	private Vector2D[] displacement_;

	public Face(Node... nodes) {
		nodes_ = new ArrayList<Node>();
		for (Node n : nodes)
			nodes_.add(n);
		edges_ = new ArrayList<IEdge>();
		setMode(0);
	}

	public Face(Node[] nodes, IEdge... edges) {
		this(nodes);
		for (IEdge e : edges)
			edges_.add(e);
	}

	@Override
	public Node getNodes(int i) {
		return nodes_.get(i);
	}

	@Override
	public ArrayList<Node> getNodes() {
		return nodes_;
	}

	@Override
	public int getNumberOfNodes() {
		return nodes_.size();
	}

	@Override
	public IEdge getEdges(int i) {
		return edges_.get(i);
	}

	@Override
	public ArrayList<IEdge> getEdges() {
		return edges_;
	}

	@Override
	public int getNumberOfEdges() {
		return edges_.size();
	}

	@Override
	public void setMode(int n) {
		nModes_ = n;
		displacement_ = new Vector2D[n];
	}

	@Override
	public void setConstraint(Constraint c) {
		constraint_ = c;
	}

	@Override
	public int getNumberOfModes() {
		return nModes_;
	}

	public int enumerateDOFs(int d, int start) {
		dofNumbers_ = new int[3][];
		// collect enumeration of nodes
		int n = 0, cnt = 0;
		for (Node node : getNodes())
			n += node.getDofNumbers().length;
		dofNumbers_[0] = new int[n];
		for (int i = 0; i < getNumberOfNodes(); i++) {
			int[] tmp = getNodes(i).getDofNumbers();
			for (int j = 0; j < tmp.length; j++)
				dofNumbers_[0][cnt++] = tmp[j];
		}
		// collect enumeration of edges
		n = 0;
		cnt = 0;
		for (IEdge e : getEdges())
			n += e.getDofNumbers().length;
		dofNumbers_[1] = new int[n];
		for (int i = 0; i < getNumberOfEdges(); i++) {
			int[] tmp = getEdges(i).getDofNumbers();
			for (int j = 0; j < tmp.length; j++)
				dofNumbers_[1][cnt++] = tmp[j];
		}

		// enumerate dof for modes on face
		dofNumbers_[2] = new int[d * getNumberOfModes()];
		for (int i = 0; i < getNumberOfModes(); i++) {
			if (constraint_ != null)
				for (int j = 0; j < d; j++)
					if (constraint_.isFree(j))
						dofNumbers_[1][d * i + j] = start++;
					else
						dofNumbers_[1][d * i + j] = -1;
			else
				for (int j = 0; j < d; j++)
					dofNumbers_[1][d * i + j] = start++;
		}
		return start;
	}

	@Override
	public int[] getDofNumbers() {
		return dofNumbers_[2];
	}

	@Override
	public void setDisplacement(double[] u) {
		for (int i = 0; i < getNumberOfModes(); i++)
			displacement_[i] = new Vector2D(u[i * 2], u[i * 2 + 1]);
	}

	@Override
	public Vector2D getDisplacement(int i) {
		return displacement_[i];
	}
}